/** @brief Fichier implémentant des convertisseurs XML vers objets.
 *
 * Ce fichier contient l'implémentation de fonctions utiles pour construires
 * différents objets depuis le contenu d'un fichier XML.
 *
 * @file InterpreteXML.cpp
 * @author Johan "Solo" Luisier
 * @date 2010
 */
#include "InterpreteXML.hpp"

#include "Utils/ATL.hpp"
#include "Utils/debugstreams.hpp"

#include "Xml/ElementDOM.hpp"

#include "Noyau/Camera.hpp"
#include "Noyau/Environnement.hpp"

#include "Lumieres/Lumiere.hpp"
#include "Lumieres/Source.hpp"
#include "Lumieres/SourceAttenuee.hpp"
#include "Lumieres/Ambiante.hpp"

#include "Materiaux/AplatCouleur.hpp"
#include "Materiaux/Carreaux.hpp"
#include "Materiaux/Texture.hpp"
#include "Materiaux/Marbre.hpp"
#include "Materiaux/MultiCouleurs.hpp"
#include "Materiaux/EffetBois.hpp"
#include "Materiaux/Melange.hpp"

#include "Formes/LibForm.hpp"

using namespace std;

bool lireContenuEtDonnees( vector< const ElementDOM* >::const_iterator& elIt,
                           const string& attendu, string& donnees )
{
    if ( (*elIt) -> balise() == attendu )
    {
        donnees = (*elIt) -> donnees();
        return true;
    }
    else
    {
        error() << "La balise n'est pas <" << attendu << "> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        return false;
    }
}

Couleur lireCouleur( const string& donnees, bool& etat )
{
    vector< unsigned int > vec;

    etat = lireDansVecteur( donnees, &vec );

    if ( ! etat )
    {
        error() << "Erreur de lecture de la couleur" << endreq;
        return Couleur();
    }

    return Couleur( static_cast<int>(vec[0]),
            static_cast<int>(vec[1]),
            static_cast<int>(vec[2]) );
}

Coord lireCoord( const string& donnees, bool& etat )
{
    return lireVecteur( donnees, etat );
    /*
  vector< double > vec;

  if ( ! lireDansVecteur( donnees, &vec ) )
    {
      error() << "Erreur de lecture du point" << endreq;
      etat = false;
      return Coord( false );
    }

  etat = true;
  return Coord( vec[0], vec[1], vec[2] );
  */
}

Vecteur lireVecteur( const string& donnees, bool& etat )
{
    vector< double > vec;

    if ( ! lireDansVecteur( donnees, &vec ) )
    {
        error() << "Erreur de lecture du point" << endreq;
        etat = false;
        return Vecteur(-1);
    }

    etat = true;
    return Vecteur( vec[0], vec[1], vec[2] );
}

Environnement* lireEnvironnement( const vector< const ElementDOM* > &infos,
                                  bool& etat )
{
    vector< const ElementDOM* >::const_iterator elIt,
            elDebut( infos.begin() ), elFin( infos.end() );

    string donnees;

    Environnement *env;

    // Vérifications
    elIt = elDebut;
    if ( (*elIt) -> balise() != "Scene" )
    {
        error() << "La première balise n'est pas <Scene>" << endreq;
        etat = false;
        return 0;
    }
    elIt++;

    if ( (*elIt) -> balise() == "Couleur" )
    {
        donnees = (*elIt) -> donnees();

        env = new Environnement( lireCouleur( donnees, etat ) );

        if ( ! etat )
        {
            error() << "Impossible de lire la couleur de fond" << endreq;
            delete env;
            return 0;
        }
    }
    else
    {
        //blank() << "Environnement de base OK" << endreq;
        env = new Environnement();
    }

    while ( (*elIt) -> balise() != "Sources" && elIt != elFin )
        elIt++;

    if ( elIt == elFin )
    {
        error() << "Pas de sources lumineuses" << endreq;
        etat = false;
        delete env;
        return 0;
    }

    const ElementDOM *ptrParent( (*(elIt + 1)) -> parent() );
    Lumiere *src;

    elIt++;
    do
    {
        src = lireLampe( elIt, etat );
        if ( ! etat )
        {
            error() << "Ne peut pas lire la source de lumière "
                    << "(probablement à cause de la syntaxe)." << endreq;
            etat = false;
            delete env;
            return 0;
        }
        else if ( src == 0 )
        {
            error() << "Ne peut pas lire la source de lumière "
                    << "(source reçue est un ptr nul)." << endreq;
            etat = false;
            delete env;
            return 0;
        }
        else
        {
            env -> ajouterLumiere( src );
            blank() << "Source de lumière OK et ajoutée" << endreq;
        }
        elIt++;
    }
    while ( elIt != elFin && (*elIt) -> parent() == ptrParent );

    if ( (*elIt) -> balise() != "Objets" )
    {
        error() << "La balise n'est pas <Objets>, mais <" << (*elIt) -> balise()
                << ">" << endreq;
        etat = false;
        delete env;
        return 0;
    }

    Objet *obj;
    ptrParent = (*(elIt + 1)) -> parent();

    elIt++;
    do
    {
        obj = lireObjet( elIt, etat );
        if ( ! etat )
        {
            error() << "Ne peut pas lire l'objet" << endreq;
        }
        else if ( obj == 0 )
        {
            error() << "Ne peut pas lire l'objet" << endreq;
        }
        else
        {
            env -> ajouterObjet( obj );
            //blank() << "Objet OK et ajouté" << endreq;
        }
        elIt++;
    }
    while ( elIt != elFin && (*elIt) -> parent() == ptrParent );

    //blank() << "Fini avec les Objets" << endreq;

    env -> affiche();

    return env;
}

Camera* lireCamera( const vector< const ElementDOM* > &infos, bool& etat )
{
    Camera* cam;
    Image* film;

    Coord position;
    VecteurU direction, hauteur;
    double distance, seuil( .3 );
    int profondeur(10), alias;
    unsigned facteurSampling( -1u ), nbrPasses( -1u );

    string donnees;
    vector< unsigned int > vecUint;
    vector< double> vecDouble;

    /*
   * Il nous faut lire un "Ecran", un "Coord", deux "Vecteur", un
   * "Distance" et un "Antialiasing".
   */
    vector< const ElementDOM* >::const_iterator elIt, elDebut( infos.begin() ),
            elFin( infos.end() );
    elIt = elDebut;

    while ( (*elIt) -> balise() != "Camera" )
        elIt++;

    if ( elIt == elFin )
    {
        error() << "Aucune balise <Camera> trouvée" << endreq;
        etat = false;
        return 0;
    }

    if ( (*elIt) -> aAttributs() )
    {
        donnees = (*elIt) -> attribut( "profondeur" );

        if ( donnees != "" )
        {
            if ( lireDansVecteur( donnees, &vecUint ) )
                profondeur = vecUint[0];
        }

        donnees = (*elIt) -> attribut( "oversampling" );

        if ( donnees != "" )
        {
            if ( lireDansVecteur( donnees, &vecUint ) )
                facteurSampling = vecUint[0];
        }
    }

    elIt++;

    if ( (*elIt) -> balise() == "Ecran" )
    {
        donnees = (*elIt) -> donnees();

        if ( ! lireDansVecteur( donnees, &vecUint ) )
        {
            error() << "Erreur de lecture de la taille de l'image" << endreq;
            etat = false;
            return 0;
        }

        film = new Image( vecUint[0], vecUint[1] );
    }
    else
    {
        error() << "La balise n'est pas <Ecran> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        etat = false;
        return 0;
    }

    elIt++;
    if ( (*elIt) -> balise() == "Coord" )
    {
        donnees = (*elIt) -> donnees();

        position = lireCoord( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la position de la caméra" << endreq;
            delete film;
            etat = false;
            return 0;
        }
    }
    else
    {
        error() << "La balise n'es pas <Coord> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        delete film;
        etat = false;
        return 0;
    }

    // direction en premier
    elIt++;
    if ( (*elIt) -> balise() == "Vecteur" )
    {
        donnees = (*elIt) -> donnees();

        direction = lireVecteur( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la direction de la caméra" << endreq;
            delete film;
            return 0;
        }
    }
    else
    {
        error() << "La balise n'es pas <Vecteur> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        delete film;
        etat = false;
        return 0;
    }

    // hauter ensuite
    elIt++;
    if ( (*elIt) -> balise() == "Vecteur" )
    {
        donnees = (*elIt) -> donnees();

        hauteur = lireVecteur( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur de la caméra" << endreq;
            delete film;
            return 0;
        }
    }
    else
    {
        error() << "La balise n'es pas <Vecteur> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        delete film;
        etat = false;
        return 0;
    }

    elIt++;
    if ( (*elIt) -> balise() == "Distance" )
    {
        donnees = (*elIt) -> donnees();

        if ( ! lireDansVecteur( donnees, &vecDouble ) )
        {
            error() << "Ne peut pas lire la distance focale" << endl;
            delete film;
            return 0;
        }
        distance = vecDouble[0];
    }
    else
    {
        error() << "La balise n'est pas <Distance> mais <"
                << (*elIt) -> balise() << '>' << endreq;
        delete film;
        etat = false;
        return 0;
    }

    elIt++;
    if ( (*elIt) -> balise() == "Antialiasing" )
    {
        donnees = (*elIt) -> donnees();

        if ( ! lireDansVecteur( donnees, &vecUint ) )
        {
            error() << "Ne peut pas lire le paramètre de l'antialiasing" << endl;
            delete film;
            etat = false;
            return 0;
        }
        alias = static_cast<int>( vecUint[0] );

        if ( (*elIt) -> aAttributs() )
        {
            donnees = (*elIt) -> attribut( "seuil" );

            if ( donnees != "" )
            {
                if ( lireDansVecteur( donnees, &vecDouble ) )
                    seuil = vecDouble[0];
            }

            donnees = (*elIt) -> attribut( "nbrpasses" );

            if ( donnees != "" )
            {
                if ( lireDansVecteur( donnees, &vecUint ) )
                    nbrPasses = vecUint[0];
            }
        }
    }
    else
        alias = 0;

    cam = new Camera( position, direction, hauteur, distance, film, 0,
                      profondeur, seuil, alias );

    if ( facteurSampling != -1u )
        cam -> setFacteurOversampling( facteurSampling );

    if ( nbrPasses != -1u )
        cam -> setNbrPasses( nbrPasses );

    return cam;
}

Lumiere* lireLampe( vector< const ElementDOM* >::const_iterator &elIt, bool& etat )
{
    /*
   * Il nous faut un "Coord" et un "Couleur" par source
   */

    Coord position;
    Couleur couleur;

    string donnees;

    string nomSource( (*elIt) -> balise() );

    Lumiere *src;

    if ( nomSource == "Lampe" )
    {
        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        position = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire la position de la Source" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Couleur", donnees );
        if ( ! etat )
            return 0;
        couleur = lireCouleur( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la couleur de la lampe" << endl;
            return 0;
        }

        src = new Source( couleur, position );
    }
    else if ( nomSource == "Etoile" )
    {
        double c1, c2, c3;
        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        position = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire la position de la SourceAttenuee"
                    << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Couleur", donnees );
        if ( ! etat )
            return 0;
        couleur = lireCouleur( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la couleur de la SourceAttenuee"
                    << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Constant", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( !etat )
        {
            error() << "Impossible de lire le coefficient d'atténuation c1"
                    << endreq;
            return 0;
        }
        c1 = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Lineaire", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( !etat )
        {
            error() << "Impossible de lire le coefficient d'atténuation c2"
                    << endreq;
            return 0;
        }
        c2 = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Quadratique", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( !etat )
        {
            error() << "Impossible de lire le coefficient d'atténuation c3"
                    << endreq;
            return 0;
        }
        c3 = vecDouble[0];

        cerr << "Position : " << position << endl;
        src = new SourceAttenuee( couleur, position, c1, c2, c3 );
    }
    else if ( nomSource == "Ambiante" )
    {
        elIt++;
        etat = lireContenuEtDonnees( elIt, "Couleur", donnees );
        if ( ! etat )
            return 0;
        couleur = lireCouleur( donnees, etat );

        if ( ! etat )
        {
            error() << "Impossible de lire la couleur de la source Ambiante"
                    << endreq;
            return 0;
        }

        double att;
        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Attenuation", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( !etat )
        {
            error() << "Impossible de lire le coefficient d'atténuation"
                    << endreq;
            return 0;
        }
        att = vecDouble[0];

        src = new Ambiante( couleur, att );
    }
    else
    {
        error() << nomSource << " n'est pas une source connue!" << endreq;
        return 0;
    }

    return src;
}


Objet* lireObjet( vector< const ElementDOM* >::const_iterator &elIt,
                  bool& etat )
{
    /*
   * Il nous faut une forme et un "Materiau" par objet
   */

    string donnees;

    if ( (*elIt) -> balise() != "Objet" )
    {
        error() << "Ce n'est pas un Objet!" << endreq;
        etat = false;
        return 0;
    }

    Objet *obj;
    Forme *forme;
    Materiau *mat;

    elIt++;
    forme = lireForme( elIt, etat );

    if ( ! etat )
    {
        error() << "Impossible de lire la forme" << endreq;
        return 0;
    }
    else if ( forme == 0 )
    {
        error() << "Impossible de lire la forme" << endreq;
        return 0;
    }

    elIt++;
    mat = lireMateriau( elIt, etat );
    if ( ! etat )
    {
        error() << "Impossible de lire le matériau" << endreq;
        delete forme;
        return 0;
    }
    else if ( mat == 0 )
    {
        error() << "Impossible de lire le matériau" << endreq;
        delete forme;
        return 0;
    }

    if ( mat -> type() == tTexture )
        static_cast< Texture* >(mat) -> setVolume( forme );
    else if ( mat -> type() == tCarreaux )
        static_cast< Carreaux* >(mat) -> setVolume( forme );

    obj = new Objet( mat, forme );

    return obj;
}

Forme* lireForme( vector< const ElementDOM* >::const_iterator &elIt,
                  bool& etat )
{
    string donnees;
    vector< double > vecDouble;

    Forme *forme;

    string nomForme;
    nomForme = (*elIt) -> balise();
    if ( nomForme == "Composee" )
    {
        // Faire attention ici !

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Operation", donnees );
        if ( ! etat )
        {
            error() << "Impossible de lire l'opération de composition" << endreq;
            return 0;
        }
        operateur oper;
        if ( donnees == "union" )
            oper = unions;
        else if ( donnees == "inter" )
            oper = inter;
        else if ( donnees == "difference" )
            oper = difference;
        else
        {
            error() << "Opération inconnue : " << donnees << endreq;
            etat = false;
            return 0;
        }

        elIt++;
        Forme *forme1 = lireForme( elIt, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire la forme 1 (etat)" << endreq;
            return 0;
        }
        else if ( forme1 == 0 )
        {
            error() << "Impossible de lire la forme 1 (nul)" << endreq;
            return 0;
        }

        elIt++;
        Forme *forme2 = lireForme( elIt, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire la forme 2 (etat)" << endreq;
            return 0;
        }
        else if ( forme2 == 0 )
        {
            error() << "Impossible de lire la forme 2 (nul)" << endreq;
            return 0;
        }

        forme = new FormeComposee(oper , forme1, forme2 );
    }
    else if ( nomForme == "Plan" )
    {
        Coord pt;
        Vecteur vec;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point du plan" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        vec = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur normal au plan" << endreq;
            return 0;
        }

        forme = new Plan( vec, pt );
    }
    else if ( nomForme == "Sphere" )
    {
        Coord pt;
        double rayon;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre de la sphère" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Rayon", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rayon de la sphère" << endreq;
            return 0;
        }
        rayon = vecDouble[0];

        forme = new Sphere( pt, rayon );
    }
    else if ( nomForme == "Parallelepipede" )
    {
        Coord pt;
        Vecteur v1, v2, v3;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point du parallèlogramme" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur v1 du trièdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur v2 du trièdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v3 = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur v3 du trièdre" << endreq;
            return 0;
        }

        forme = new Parallelepipede( pt, v1, v2, v3 );
    }
    else if ( nomForme == "Cube" )
    {
        Coord pt;
        Vecteur v1, v2;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point du cube" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur v1 du cube" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireVecteur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur v2 du cube" << endreq;
            return 0;
        }

        forme = new Cube( pt, v1, v2 );
    }
    else if ( nomForme == "Pyramide" )
    {
        Coord pt1, pt2, pt3, pt4;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt1 de la pyramide" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt2 de la pyramide" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt3 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt3 de la pyramide" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt4 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le sommet de la pyramide" << endreq;
            return 0;
        }

        forme = new Pyramide( pt1, pt2, pt3, pt4 );
    }
    else if ( nomForme == "Tetraedre" )
    {
        Coord pt1, pt2, pt3, pt4;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt1 du tetraèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt2 du tetraèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt3 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt3 du tetraèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt4 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le pt4 du tetraèdre" << endreq;
            return 0;
        }

        forme = new Tetraedre( pt1, pt2, pt3, pt4 );
    }
    else if ( nomForme == "Octaedre" )
    {
        Coord pt1, pt2, pt3, pt4;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt1 de l'octaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt2 de l'octaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt3 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point pt3 de l'octaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt4 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le sommet de l'octaèdre" << endreq;
            return 0;
        }

        forme = new Octaedre( pt1, pt2, pt3, pt4 );
    }
    else if ( nomForme == "Dodecaedre" )
    {
        Coord pt;
        Vecteur v1, v2;
        double ratio;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre du dodécaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe 1 du dodécaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe 2 du dodécaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Cote", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rapport d'homothétie du cube troué"
                    << endreq;
            return 0;
        }
        ratio = vecDouble[0];

        forme = new Dodecaedre( pt, v1, v2, ratio );
    }
    else if ( nomForme == "Cylindre" )
    {
        Coord pt;
        Vecteur vec;
        double r, h;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point du cylindre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        vec = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe du cylindre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Rayon", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rayon du cylindre" << endreq;
            return 0;
        }
        r = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Hauteur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur du cylindre" << endreq;
            return 0;
        }
        h = vecDouble[0];

        forme = new Cylindre( vec, pt, r, h );
    }
    else if ( nomForme == "Tore" )
    {
        Coord pt;
        Vecteur vec;
        double R, r;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre du tore" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        vec = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe du tore" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Grand", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le grand rayon du tore" << endreq;
            return 0;
        }
        R = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Petit", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le petit rayon du tore" << endreq;
            return 0;
        }
        r = vecDouble[0];

        forme = new Tore( pt, vec, R, r );
    }
    else if ( nomForme == "CubeTroue" )
    {
        Coord pt;
        Vecteur v1, v2;
        double ratio;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le coin du cube troué" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur 1 du cube troué" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le vecteur 1 du cube troué" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Cote", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rapport d'homothétie du cube troué"
                    << endreq;
            return 0;
        }
        ratio = vecDouble[0];

        forme = new CubeTroue( pt, v1, v2, ratio );
    }
    else if ( nomForme == "Cone" )
    {
        Coord pt;
        Vecteur vec;
        double angle, hauteur;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le point du cône" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        vec = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe du cône" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Angle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire l'angle du cône" << endreq;
            return 0;
        }
        angle = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Hauteur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur du cylindre" << endreq;
            return 0;
        }
        hauteur = vecDouble[0];

        forme = new Cone( pt, vec, angle, hauteur );
    }

    else if ( nomForme == "Icosaedre" )
    {
        Coord pt;
        Vecteur v1, v2;
        double ratio;

        vector< double > vecDouble;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre de l'icosaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe 1 de l'icosaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe 2 de l'icosaèdre" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Cote", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rapport d'homothétie de l'icosaèdre"
                    << endreq;
            return 0;
        }
        ratio = vecDouble[0];

        forme = new Icosaedre( pt, v1, v2, ratio );
    }
    else if ( nomForme == "Ellipsoide" )
    {
        Coord pt;
        Vecteur v1, v2;
        double rx, ry, rz;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre de l'ellipsoïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe x de l'ellipsoïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe y de l'ellipsoïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Rayon", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rayon Ox de l'ellipsoïde"
                    << endreq;
            return 0;
        }
        rx = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Rayon", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rayon Oy de l'ellipsoïde"
                    << endreq;
            return 0;
        }
        ry = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Rayon", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le rayon Oz de l'ellipsoïde"
                    << endreq;
            return 0;
        }
        rz = vecDouble[0];

        forme = new Ellipsoide( pt, v1, v2, rx, ry, rz );
    }
    else if ( nomForme == "Paraboloide" )
    {
        Coord pt;
        Vecteur v1, v2, v3;
        double rx, ry, h;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre du paraboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe x du paraboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe y du paraboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v3 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe z du paraboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "FacteurEchelle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le facteur d'échelle Ox du paraboloïde"
                    << endreq;
            return 0;
        }
        rx = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "FacteurEchelle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le facteur d'échelle Oy du paraboloïde"
                    << endreq;
            return 0;
        }
        ry = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Hauteur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur du paraboloïde"
                    << endreq;
            return 0;
        }
        h = vecDouble[0];

        forme = new Paraboloide( pt, v1, v2, v3, rx, ry, h );
    }
    else if ( nomForme == "Hyperboloide" )
    {
        Coord pt;
        Vecteur v1, v2, v3;
        double rx, ry, rz, hPlus, hMoins;

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coord", donnees );
        if ( ! etat )
            return 0;
        pt = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire le centre de l'hyperboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v1 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe x de l'hyperboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v2 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe y de l'hyperboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Vecteur", donnees );
        if ( ! etat )
            return 0;
        v3 = lireCoord( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire l'axe z de l'hyperboloïde" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "FacteurEchelle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le facteur d'échelle Ox de l'hyperboloïde"
                    << endreq;
            return 0;
        }
        rx = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "FacteurEchelle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le facteur d'échelle Oy de l'hyperboloïde"
                    << endreq;
            return 0;
        }
        ry = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "FacteurEchelle", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le facteur d'échelle Oz de l'hyperboloïde"
                    << endreq;
            return 0;
        }
        rz = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Hauteur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur (+) de l'hyperboloïde"
                    << endreq;
            return 0;
        }
        hPlus = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Hauteur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la hauteur (-) de l'hyperboloïde"
                    << endreq;
            return 0;
        }
        hMoins = vecDouble[0];

        //forme = new BaseHyperboloide( pt, v1, v2, v3, rx, ry, rz );
        forme = new Hyperboloide( pt, v1, v2, v3, rx, ry, rz, hPlus, hMoins );
    }
    else
    {
        error() << "Forme " << nomForme << " inconnu" << endreq;
        forme = 0;
        etat = false;
    }

    return forme;
}

Materiau* lireMateriau( vector< const ElementDOM* >::const_iterator &elIt,
                        bool& etat )
{
    /*
   * 4 possibilités ici :
   * - couleur toute simple (=> "Couleur")
   * - couleur avec bruit de Perlin (=> "Bruit" puis "Couleur")
   * - un "Carreau", comprenant deux "Couleur" et un "Largeur"
   * - un "Texture", comprenant un "Fichier" et un "Fréquence"
   * La suite est rigide, un "Reflex", un "Diffuz", un "Transp" et un
   * "Indice".
   */

    string donnees;
    vector< double > vecDouble;

    vector< Couleur > cols;
    vector< double > mel;

    if ( (*elIt) -> balise() != "Materiau" )
    {
        error() << "Ce n'est pas un matériau, la balise est <"
                << (*elIt) -> balise() << '>' << endreq;
        etat = false;
        return 0;
    }

    TypeMateriau type;

    if ( ( *(elIt + 1) ) -> balise() == "Couleur" )
        type = tCouleurSimple;
    else if ( ( *(elIt + 1) ) -> balise() == "Bruit" )
        type = tPerlin;
    else if ( ( *(elIt + 1) ) -> balise() == "Carreaux" )
        type = tCarreaux;
    else if ( ( *(elIt + 1) ) -> balise() == "Texture" )
        type = tTexture;
    else if ( ( *(elIt + 1) ) -> balise() == "Marbre" )
        type = tMarbre;
    else if ( ( *(elIt + 1) ) -> balise() == "Multi" )
        type = tMultiCouleurs;
    else if ( ( *(elIt + 1) ) -> balise() == "Bois" )
        type = tEffetBois;
    else
    {
        error() << "Balise inconnue dans <Materiau> : "
                << ( *(elIt + 1) ) -> balise() << endreq;
        return 0;
    }

    double bruit( 0. ), repetition;
    Couleur couleur, couleurBis;
    string fichier;

    elIt++;
    switch (type)
    {
    case tCouleurSimple:
        donnees = (*elIt) -> donnees();
        couleur = lireCouleur( donnees, etat );
        if ( ! etat )
        {
            error() << "Impossible de lire la couleur" << endreq;
            return 0;
        }
        break;
    case tPerlin:
        donnees = (*elIt) -> donnees();
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le bruit" << endreq;
            return 0;
        }
        bruit = vecDouble[0];

        elIt++;
        if ( (*elIt) -> balise() == "Couleur" )
        {
            donnees = (*elIt) -> donnees();
            couleur = lireCouleur( donnees, etat );
            if ( ! etat )
            {
                error() << "Impossible de lire la couleur" << endreq;
                return 0;
            }
        }
        else
        {
            error() << "La balise n'est pas <Couleur> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }
        break;
    case tCarreaux:
        // cerr << "On a des carreaux" << endl;
        elIt++;
        if ( (*elIt) -> balise() == "Couleur" )
        {
            // cerr << "Couleur 1 OK" << endl;
            donnees = (*elIt) -> donnees();
            couleur = lireCouleur( donnees, etat );
            if ( ! etat )
            {
                error() << "Impossible de lire la couleur" << endreq;
                return 0;
            }
        }
        else
        {
            error() << "La balise n'est pas <Couleur> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }

        elIt++;
        if ( (*elIt) -> balise() == "Couleur" )
        {
            donnees = (*elIt) -> donnees();
            couleurBis = lireCouleur( donnees, etat );
            if ( ! etat )
            {
                error() << "Impossible de lire la couleur" << endreq;
                return 0;
            }
        }
        else
        {
            error() << "La balise n'est pas <Couleur> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Largeur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la largeur des carreaux" << endreq;
            return 0;
        }
        bruit = vecDouble[0];

        break;
    case tTexture:
        elIt++;
        if ( (*elIt) -> balise() == "Fichier" )
        {
            fichier = (*elIt) -> donnees();
        }
        else
        {
            error() << "La balise n'est pas <Fichier> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }

        elIt++;
        if ( (*elIt) -> balise() == "Repetition" )
        {
            donnees = (*elIt) -> donnees();
            etat = lireDansVecteur( donnees, &vecDouble );
            if ( ! etat )
            {
                error() << "Impossible de lire la répétition" << endreq;
                return 0;
            }
            repetition = vecDouble[0];
        }
        else
        {
            error() << "La balise n'est pas <Repetition> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }
        break;
    case tMarbre:

        do
        {
            elIt++;
            if ( (*elIt) -> balise() == "Couleur" )
            {
                // cerr << "Couleur 1 OK" << endl;
                donnees = (*elIt) -> donnees();
                couleur = lireCouleur( donnees, etat );
                if ( ! etat )
                {
                    error() << "Impossible de lire la couleur" << endreq;
                    return 0;
                }
            }
            else
            {
                error() << "La balise n'est pas <Couleur> mais <"
                        << (*elIt) -> balise() << '>' << endreq;
                return 0;
            }
            cols.push_back( couleur );
        }
        while ( cols.size() != 2 );

        /*
      elIt++;
      etat = lireContenuEtDonnees( elIt, "Bornes", donnees );
      if ( ! etat )
    return 0;
      etat = lireDansVecteur( donnees, &mel );
      if ( ! etat )
    {
      error() << "Impossible de lire les coefficients de mélange" << endreq;
      return 0;
    }

      if ( mel.size() != 4 )
        {
      error() << "Taille inappropriée pour les coefficients de mélange"
          << endreq;
      return 0;
    }
      */

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coefficient", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire le coefficient de pondération"
                    << endreq;
            return 0;
        }
        bruit = vecDouble[ 0 ];

        break;
    case tMultiCouleurs:

        do
        {
            elIt++;
            if ( (*elIt) -> balise() == "Couleur" )
            {
                // cerr << "Couleur 1 OK" << endl;
                donnees = (*elIt) -> donnees();
                couleur = lireCouleur( donnees, etat );
                if ( ! etat )
                {
                    error() << "Impossible de lire la couleur" << endreq;
                    return 0;
                }
            }
            else
            {
                error() << "La balise n'est pas <Couleur> mais <"
                        << (*elIt) -> balise() << '>' << endreq;
                return 0;
            }
            cols.push_back( couleur );
        }
        while ( (*elIt + 1 )  -> balise() == "Couleur" );

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Bornes", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &mel );
        if ( ! etat )
        {
            error() << "Impossible de lire les coefficients de mélange" << endreq;
            return 0;
        }

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coefficient", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire les seuils" << endreq;
            return 0;
        }
        bruit = vecDouble[0];
        break;
    case tEffetBois:
        elIt++;
        if ( (*elIt) -> balise() == "Couleur" )
        {
            // cerr << "Couleur 1 OK" << endl;
            donnees = (*elIt) -> donnees();
            couleur = lireCouleur( donnees, etat );
            if ( ! etat )
            {
                error() << "Impossible de lire la couleur" << endreq;
                return 0;
            }
        }
        else
        {
            error() << "La balise n'est pas <Couleur> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }
        cols.push_back( couleur );

        elIt++;
        if ( (*elIt) -> balise() == "Couleur" )
        {
            donnees = (*elIt) -> donnees();
            couleur = lireCouleur( donnees, etat );
            if ( ! etat )
            {
                error() << "Impossible de lire la couleur" << endreq;
                return 0;
            }
        }
        else
        {
            error() << "La balise n'est pas <Couleur> mais <"
                    << (*elIt) -> balise() << '>' << endreq;
            return 0;
        }
        cols.push_back( couleur );

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Coefficient", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la largeur des carreaux" << endreq;
            return 0;
        }
        bruit = vecDouble[0];

        elIt++;
        etat = lireContenuEtDonnees( elIt, "Multiplicateur", donnees );
        if ( ! etat )
            return 0;
        etat = lireDansVecteur( donnees, &vecDouble );
        if ( ! etat )
        {
            error() << "Impossible de lire la largeur des carreaux" << endreq;
            return 0;
        }
        repetition = vecDouble[0];

        break;
    }

    // Il faut encore lire les indices, puis construire le matériau
    double reflex, diffuz, transp, indice;

    elIt++;
    etat = lireContenuEtDonnees( elIt, "Reflex", donnees );
    if ( ! etat )
        return 0;
    etat = lireDansVecteur( donnees, &vecDouble );
    if ( ! etat )
    {
        error() << "Impossible de lire l'indice de réflexion" << endreq;
        return 0;
    }
    reflex = vecDouble[0];

    elIt++;
    etat = lireContenuEtDonnees( elIt, "Diffuz", donnees );
    if ( ! etat )
        return 0;
    etat = lireDansVecteur( donnees, &vecDouble );
    if ( ! etat )
    {
        error() << "Impossible de lire l'indice de diffusion" << endreq;
        return 0;
    }
    diffuz = vecDouble[0];

    elIt++;
    etat = lireContenuEtDonnees( elIt, "Transp", donnees );
    if ( ! etat )
        return 0;
    etat = lireDansVecteur( donnees, &vecDouble );
    if ( ! etat )
    {
        error() << "Impossible de lire la transparence" << endreq;
        return 0;
    }
    transp = vecDouble[0];

    elIt++;
    etat = lireContenuEtDonnees( elIt, "Indice", donnees );
    if ( ! etat )
        return 0;
    etat = lireDansVecteur( donnees, &vecDouble );
    if ( ! etat )
    {
        error() << "Impossible de lire l'indice de réfraction" << endreq;
        return 0;
    }
    indice = vecDouble[0];

    Materiau *mat;

    switch ( type )
    {
    case tCouleurSimple:
        mat = new AplatCouleur( reflex, transp, indice, diffuz, couleur );
        break;
    case tPerlin:
        mat = new AplatCouleur( reflex, transp, indice, diffuz, bruit, couleur );
        break;
    case tCarreaux:
        mat = new Carreaux( reflex, transp, indice, diffuz,
                            couleur, couleurBis, bruit );
        break;
    case tTexture:
        mat = new Texture( reflex, transp, indice, diffuz,
                           fichier, 0, repetition );
        break;
    case tMarbre:
        mat = new Marbre( reflex, transp, indice, diffuz,
                          cols, bruit );
        break;
    case tMultiCouleurs:
        mat = new MultiCouleurs( reflex, transp, indice, diffuz,
                                 cols, mel, bruit );
        break;
    case tEffetBois:
        mat = new EffetBois( reflex, transp, indice, diffuz,
                             cols, bruit, repetition );
        break;
    }

    return mat;
}
